package com.app.brilliant.game.service.impl;

import cn.hutool.http.HttpUtil;
import com.app.brilliant.game.service.WxPayService;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.*;

@Service
public class WxPayServiceImpl implements WxPayService {
    @Value("${wx.pay.appid}")
    private String appId;
    @Value("${wx.pay.mchid}")
    private String mchId;
    @Value("${wx.pay.key}")
    private String apiKey;
    @Value("${wx.pay.notify-url}")
    private String notifyUrl;

    @Override
    public String generateNativePayQrCode(String orderId, BigDecimal amount, String description) throws Exception {
        // 1. 构造请求参数
        SortedMap<String, String> params = new TreeMap<>();
        params.put("appid", appId);
        params.put("mch_id", mchId);
        params.put("nonce_str", generateNonceStr());
        params.put("body", description);
        params.put("out_trade_no", orderId);
        params.put("total_fee", amount.toString());
        params.put("spbill_create_ip", "127.0.0.1");
        params.put("notify_url", notifyUrl);
        params.put("trade_type", "NATIVE");
        params.put("sign", generateSign(params));

        // 2. 转换为XML并调用微信支付统一下单API
        String xml = mapToXml(params);
        String result = HttpUtil.post("https://api.mch.weixin.qq.com/pay/unifiedorder", xml);
        Map<String, String> resultMap = xmlToMap(result);

        // 3. 处理返回结果
        if ("SUCCESS".equals(resultMap.get("return_code")) && "SUCCESS".equals(resultMap.get("result_code"))) {
            return resultMap.get("code_url");
        } else {
            throw new RuntimeException("微信支付下单失败：" + resultMap.get("return_msg"));
        }
    }

    @Override
    public Map<String, String> parseRequest(HttpServletRequest request) {
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                request.getInputStream(), StandardCharsets.UTF_8));
            StringBuilder sb = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
            return xmlToMap(sb.toString());
        } catch (Exception e) {
            throw new RuntimeException("解析微信支付回调请求失败", e);
        }
    }

    @Override
    public boolean verifySign(Map<String, String> params) {
        String sign = params.get("sign");
        if (sign == null || sign.isEmpty()) {
            return false;
        }
        SortedMap<String, String> sortedParams = new TreeMap<>(params);
        sortedParams.remove("sign");
        String calculatedSign = generateSign(sortedParams);
        return sign.equals(calculatedSign);
    }

    private String generateNonceStr() {
        return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
    }

    private String generateSign(SortedMap<String, String> params) {
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (entry.getValue() != null && !entry.getValue().isEmpty()) {
                sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
            }
        }
        sb.append("key=").append(apiKey);
        return DigestUtils.md5Hex(sb.toString()).toUpperCase();
    }

    private String mapToXml(Map<String, String> params) {
        StringBuilder xml = new StringBuilder("<xml>");
        for (Map.Entry<String, String> entry : params.entrySet()) {
            xml.append("<")
               .append(entry.getKey())
               .append(">")
               .append(entry.getValue())
               .append("</")
               .append(entry.getKey())
               .append(">");
        }
        xml.append("</xml>");
        return xml.toString();
    }

    private Map<String, String> xmlToMap(String xml) {
        Map<String, String> map = new HashMap<>();
        try {
            org.jsoup.nodes.Document document = org.jsoup.Jsoup.parse(xml);
            org.jsoup.nodes.Element root = document.select("xml").first();
            if (root != null) {
                for (org.jsoup.nodes.Element element : root.children()) {
                    map.put(element.tagName(), element.text());
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("XML解析失败", e);
        }
        return map;
    }
}